﻿package net.wangit.framework.interceptor;

import net.wangit.Invocation;
import net.wangit.LabelUtil;
import net.wangit.Page;
import net.wangit.Unit;
import net.wangit.User;
import net.wangit.context.ActionContext;
import net.wangit.framework.action.ActionMapping;
import net.wangit.framework.dispatcher.DefaultInvocation;
import net.wangit.framework.util.ResponseWriter;
import net.wangit.support.ActionInterceptor;
import net.wangit.support.PageInterceptor;
import net.wangit.support.UnitInterceptor;
import net.wangit.user.Developer;
import net.wangit.view.element.ElementComponent;
import net.wangit.view.page.PageFactory;
import net.wangit.view.page.PageHelper;
import net.wangit.view.page.PageImpl;
import net.wangit.view.unit.UnitComponent;
/**
 * 权限检查，包括Action、页面和元素
 * @author watson
 *
 */
public class ACI implements PageInterceptor, UnitInterceptor, ActionInterceptor {

	private static String PAGE_FAILED = "accessfailed";
	private static String URL_FAILED = "/app/accessfailed.do";

	public ACI() {
	}

	public void intercept(ActionContext ac, Invocation invocation)
			throws Exception {
		ActionMapping am = ((DefaultInvocation) invocation).getActionMapping();
		User user = ac.getVisitor().getUser();
		if (!am.isPublished()) {
			if (!(user instanceof Developer)) {
				ac.getActionResult().setSuccessful(false);
				ac.getActionResult().setUrl(URL_FAILED);
				return;
			}
		} else if (am.hasAccessPrivilege() && !user.hasActionPrivilege(am)) {
			ac.getActionResult().setSuccessful(false);
			ac.getActionResult().setUrl(URL_FAILED);
			return;
		}
		invocation.invoke();
	}

	public void intercept(ActionContext ac, Page page) throws Exception {
		UnitComponent uc = ((PageImpl) page).getUnitComponent();
		User user = ac.getVisitor().getUser();
		if (!uc.isPublished()) {
			if (!(user instanceof Developer)) {
				String url = PageHelper.getUrl(uc);
				ResponseWriter.write(LabelUtil.get(ac, "system",
						"url.page_not_found", url));
				return;
			}
		} else if (uc.hasAccessPrivileges()) {
			if (!hasUnitPrivilege(uc, user)) {
				Page failedPage = PageFactory.getPage(ac, "app", PAGE_FAILED);
				failedPage.write(ac);
				return;
			}
		} else {
			filterElements(uc, user);
		}
		page.write(ac);
	}

	public String intercept(ActionContext ac, Unit unit) throws Exception {
		UnitComponent uc = (UnitComponent) unit;
		if (uc.getParent() == null)
			return unit.write(ac);
		User user = ac.getVisitor().getUser();
		if (!uc.isPublished()) {
			if (!(user instanceof Developer))
				return (new StringBuilder(
						"<span style='color:red'>unpublished unit: ")).append(
						uc.getId()).append("!</span>").toString();
		} else if (uc.hasAccessPrivileges()) {
			if (!hasUnitPrivilege(uc, user))
				return "";
		} else {
			filterElements(uc, user);
		}
		return unit.write(ac);
	}

	private boolean hasUnitPrivilege(UnitComponent uc, User user) {
		boolean pass = user.hasUnitPrivilege(uc.getDomain(), uc.getId(), uc
				.getShowMode());
		if (pass)
			filterElements(uc, user);
		return pass;
	}

	private void filterElements(UnitComponent uc, User user) {
		if (uc.hasElementAccessPrivileges()) {
			for (int i = 0; i < uc.size(); i++) {
				ElementComponent element = (ElementComponent) uc.getElement(i);
				if (element.hasAccessPrivilege()
						&& !user.hasElementPrivilege(element))
					element.setShowMode(element.getRejectResult());
			}

		}
	}

}
